using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace ESTPrototype
{
    public partial class Thumbnail : UserControl
    {
        private enum MouseEvent { Down, Up, Move };

        public Thumbnail()
        {
            InitializeComponent();

            this.mFont = new Font(FontFamily.GenericSansSerif, 40.0f);

            base.MouseDown += this.cMouseDown;
            this.pictureBox1.MouseDown += this.cMouseDown;
            this.label1.MouseDown += this.cMouseDown;

            base.MouseUp += this.cMouseUp;
            this.pictureBox1.MouseUp += this.cMouseUp;
            this.label1.MouseUp += this.cMouseUp;

            base.MouseMove += this.cMouseMove;
            this.pictureBox1.MouseMove += this.cMouseMove;
            this.label1.MouseMove += this.cMouseMove;
        }

        public Label Label
        {
            get
            {
                return this.label1;
            }
        }

        public void SetNumber(int pNumber)
        {
            Image image = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height);
            
            // get the graphics from the picture box
            using (Graphics graphics = Graphics.FromImage(image))
            {
                graphics.DrawString(pNumber.ToString(), this.mFont, Brushes.Red, 21, 5);
            }

            this.pictureBox1.Image = image;

            this.label1.Text = pNumber.ToString();
        }

        private void FireMouseEvent(MouseEvent pMouseEvent, MouseEventArgs pEventArgs, Point pMousePositionOffset)
        {
            // calculate the offeset mouse position
            int x = pEventArgs.X + pMousePositionOffset.X;
            int y = pEventArgs.Y + pMousePositionOffset.Y;

            // clone the event args but use our new mouse coordinates
            MouseEventArgs eventArgs = new MouseEventArgs(pEventArgs.Button, pEventArgs.Clicks, x, y, pEventArgs.Delta);

            // check which mouse event were trying to fire
            switch (pMouseEvent)
            {
                case MouseEvent.Down:
                    {
                        // first make sure this point is different than the last one used for this event
                        if (this.mLastFiredMouseDownPosition == eventArgs.Location)
                        {
                            // this is the same point so just leave
                            return;
                        }

                        // if we made it this far then this is a new point so set it as the last fired one
                        this.mLastFiredMouseDownPosition = eventArgs.Location;

                        // and finally fire the event
                        if (this.MouseDown != null)
                        {
                            this.MouseDown.Invoke(this, eventArgs);
                        }

                        break;
                    }

                case MouseEvent.Up:
                    {
                        // first make sure this point is different than the last one used for this event
                        if (this.mLastFiredMouseUpPosition == eventArgs.Location)
                        {
                            // this is the same point so just leave
                            return;
                        }

                        // if we made it this far then this is a new point so set it as the last fired one
                        this.mLastFiredMouseUpPosition = eventArgs.Location;

                        // and finally fire the event
                        if (this.MouseUp != null)
                        {
                            this.MouseUp.Invoke(this, eventArgs);
                        }

                        break;
                    }

                case MouseEvent.Move:
                    {
                        // first make sure this point is different than the last one used for this event
                        if (this.mLastFiredMouseMovePosition == eventArgs.Location)
                        {
                            // this is the same point so just leave
                            return;
                        }

                        // if we made it this far then this is a new point so set it as the last fired one
                        this.mLastFiredMouseMovePosition = eventArgs.Location;

                        // and finally fire the event
                        if (this.MouseMove != null)
                        {
                            this.MouseMove.Invoke(this, eventArgs);
                        }

                        break;
                    }
            }
        }

        private void cMouseDown(object pSender, MouseEventArgs pEventArgs)
        {
            // check if the sender is ourselves
            if (this == pSender)
            {
                // fire this event with no offset
                this.FireMouseEvent(MouseEvent.Down, pEventArgs, Point.Empty);
            }

            // or check if this is a child under ourselves
            else
            {
                // fire this event with the position of this control as the offset
                this.FireMouseEvent(MouseEvent.Down, pEventArgs, ((Control)pSender).Location);
            }
        }

        private void cMouseUp(object pSender, MouseEventArgs pEventArgs)
        {
            // check if the sender is ourselves
            if (this == pSender)
            {
                // fire this event with no offset
                this.FireMouseEvent(MouseEvent.Up, pEventArgs, Point.Empty);
            }

            // or check if this is a child under ourselves
            else
            {
                // fire this event with the position of this control as the offset
                this.FireMouseEvent(MouseEvent.Up, pEventArgs, ((Control)pSender).Location);
            }
        }

        private void cMouseMove(object pSender, MouseEventArgs pEventArgs)
        {
            // check if the sender is ourselves
            if (this == pSender)
            {
                // fire this event with no offset
                this.FireMouseEvent(MouseEvent.Move, pEventArgs, Point.Empty);
            }

            // or check if this is a child under ourselves
            else
            {
                // fire this event with the position of this control as the offset
                this.FireMouseEvent(MouseEvent.Move, pEventArgs, ((Control)pSender).Location);
            }

        }

        public new event MouseEventHandler MouseDown;
        public new event MouseEventHandler MouseUp;
        public new event MouseEventHandler MouseMove;

        private Point mLastFiredMouseDownPosition;
        private Point mLastFiredMouseUpPosition;
        private Point mLastFiredMouseMovePosition;

        private Font mFont;
    }
}
